﻿// Decompiled with JetBrains decompiler
// Type: TaleWorlds.MountAndBlade.View.MissionViews.MissionGamepadEffectsView
// Assembly: TaleWorlds.MountAndBlade.View, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
// MVID: 61152EB8-513B-4D4A-8AC0-0D1465C6CF6C
// Assembly location: D:\steam\steamapps\common\Mount & Blade II Bannerlord\Modules\Native\bin\Win64_Shipping_Client\TaleWorlds.MountAndBlade.View.dll

using System;
using TaleWorlds.Core;
using TaleWorlds.DotNet;
using TaleWorlds.Engine;
using TaleWorlds.Engine.Options;
using TaleWorlds.Library;

#nullable disable
namespace TaleWorlds.MountAndBlade.View.MissionViews
{
  [DefaultView]
  public class MissionGamepadEffectsView : MissionView
  {
    private MissionGamepadEffectsView.TriggerState _triggerState;
    private readonly byte[] _triggerFeedback = new byte[4];
    private bool _isAdaptiveTriggerEnabled;
    private bool _usingAlternativeAiming;
    private RangedSiegeWeapon _currentlyUsedSiegeWeapon;
    private UsableMissionObject _currentlyUsedMissionObject;

    public override void OnMissionStateActivated()
    {
      base.OnMissionStateActivated();
      this.ResetTriggerFeedback();
      this.ResetTriggerVibration();
      this._isAdaptiveTriggerEnabled = (double) NativeOptions.GetConfig(NativeOptions.NativeOptionsType.EnableVibration) != 0.0;
      this._usingAlternativeAiming = (double) NativeOptions.GetConfig(NativeOptions.NativeOptionsType.EnableAlternateAiming) != 0.0;
      NativeOptions.OnNativeOptionChanged += new NativeOptions.OnNativeOptionChangedDelegate(this.OnNativeOptionChanged);
      TaleWorlds.InputSystem.Input.OnGamepadActiveStateChanged += new Action(this.OnGamepadActiveStateChanged);
    }

    private void OnGamepadActiveStateChanged()
    {
      if (TaleWorlds.InputSystem.Input.IsGamepadActive)
        return;
      this.ResetTriggerFeedback();
      this.ResetTriggerVibration();
    }

    public override void OnMissionStateDeactivated()
    {
      base.OnMissionStateDeactivated();
      this.ResetTriggerFeedback();
      this.ResetTriggerVibration();
      NativeOptions.OnNativeOptionChanged -= new NativeOptions.OnNativeOptionChangedDelegate(this.OnNativeOptionChanged);
      TaleWorlds.InputSystem.Input.OnGamepadActiveStateChanged -= new Action(this.OnGamepadActiveStateChanged);
    }

    public override void OnPreMissionTick(float dt)
    {
      base.OnPreMissionTick(dt);
      Agent mainAgent = this.Mission.MainAgent;
      if (!this._isAdaptiveTriggerEnabled)
        return;
      if (mainAgent != null && mainAgent.State == AgentState.Active && mainAgent.CombatActionsEnabled && !mainAgent.IsCheering && !this.Mission.IsOrderMenuOpen && this.IsMissionModeApplicableForAdaptiveTrigger(this.Mission.Mode))
      {
        MissionWeapon wieldedWeapon = mainAgent.WieldedWeapon;
        WeaponComponentData currentUsageItem1 = wieldedWeapon.CurrentUsageItem;
        int num = currentUsageItem1 != null ? (currentUsageItem1.WeaponFlags.HasAllFlags<WeaponFlags>(WeaponFlags.StringHeldByHand) ? 1 : 0) : 0;
        WeaponComponentData currentUsageItem2 = wieldedWeapon.CurrentUsageItem;
        bool flag1 = (currentUsageItem2 != null ? (currentUsageItem2.WeaponFlags.HasAllFlags<WeaponFlags>(WeaponFlags.HasString) ? 1 : 0) : 0) != 0 && !wieldedWeapon.CurrentUsageItem.WeaponFlags.HasAllFlags<WeaponFlags>(WeaponFlags.StringHeldByHand);
        WeaponComponentData currentUsageItem3 = wieldedWeapon.CurrentUsageItem;
        bool flag2 = (currentUsageItem3 != null ? (currentUsageItem3.IsRangedWeapon ? 1 : 0) : 0) != 0 && wieldedWeapon.CurrentUsageItem.IsConsumable;
        WeaponComponentData currentUsageItem4 = wieldedWeapon.CurrentUsageItem;
        bool flag3 = (currentUsageItem4 != null ? (currentUsageItem4.WeaponFlags.HasAllFlags<WeaponFlags>(WeaponFlags.MeleeWeapon) ? 1 : 0) : 0) != 0 || mainAgent.WieldedOffhandWeapon.IsShield();
        if (num != 0)
          this.HandleBowAdaptiveTriggers();
        else if (flag1)
          this.HandleCrossbowAdaptiveTriggers();
        else if (flag2)
          this.HandleThrowableAdaptiveTriggers();
        else if (flag3)
          this.HandleMeleeAdaptiveTriggers();
        else if (mainAgent.CurrentlyUsedGameObject != null)
        {
          if (mainAgent.CurrentlyUsedGameObject != this._currentlyUsedMissionObject)
          {
            if (this.GetUsableMachineFromUsableMissionObject(mainAgent.CurrentlyUsedGameObject) is RangedSiegeWeapon usableMissionObject)
              this._currentlyUsedSiegeWeapon = usableMissionObject;
            this._currentlyUsedMissionObject = mainAgent.CurrentlyUsedGameObject;
          }
          if (this._currentlyUsedSiegeWeapon == null)
            return;
          this.HandleRangedSiegeEngineAdaptiveTriggers(this._currentlyUsedSiegeWeapon);
        }
        else
        {
          this._currentlyUsedSiegeWeapon = (RangedSiegeWeapon) null;
          this._currentlyUsedMissionObject = (UsableMissionObject) null;
          this.ResetTriggerFeedback();
          this.ResetTriggerVibration();
        }
      }
      else
      {
        this.ResetTriggerFeedback();
        this.ResetTriggerVibration();
      }
    }

    public override void OnAgentHit(
      Agent affectedAgent,
      Agent affectorAgent,
      in MissionWeapon affectorWeapon,
      in Blow blow,
      in AttackCollisionData attackCollisionData)
    {
      base.OnAgentHit(affectedAgent, affectorAgent, in affectorWeapon, in blow, in attackCollisionData);
      if (affectedAgent == Agent.Main)
      {
        if (attackCollisionData.CollisionResult == CombatCollisionResult.Blocked || attackCollisionData.CollisionResult == CombatCollisionResult.ChamberBlocked || attackCollisionData.CollisionResult == CombatCollisionResult.Parried)
        {
          float[] leftTriggerAmplitudes = new float[1]
          {
            0.5f
          };
          float[] leftTriggerFrequencies = new float[1]
          {
            0.3f
          };
          float[] leftTriggerDurations = new float[1]
          {
            0.3f
          };
          this.SetTriggerVibration(leftTriggerAmplitudes, leftTriggerFrequencies, leftTriggerDurations, leftTriggerDurations.Length, (float[]) null, (float[]) null, (float[]) null, 0);
          this.SetTriggerState(MissionGamepadEffectsView.TriggerState.Off);
        }
        if (!affectedAgent.WieldedOffhandWeapon.IsEmpty || !attackCollisionData.AttackBlockedWithShield)
          return;
        this.SetTriggerState(MissionGamepadEffectsView.TriggerState.Off);
      }
      else
      {
        if (affectorAgent != Agent.Main || attackCollisionData.CollisionResult != CombatCollisionResult.StrikeAgent && attackCollisionData.CollisionResult != CombatCollisionResult.Blocked)
          return;
        MissionWeapon missionWeapon = affectorWeapon;
        if (missionWeapon.IsEmpty)
          return;
        missionWeapon = affectorWeapon;
        if (!missionWeapon.IsShield())
          return;
        float[] leftTriggerAmplitudes = new float[1]{ 1f };
        float[] leftTriggerFrequencies = new float[1]
        {
          0.1f
        };
        float[] leftTriggerDurations = new float[1]{ 0.35f };
        this.SetTriggerVibration(leftTriggerAmplitudes, leftTriggerFrequencies, leftTriggerDurations, leftTriggerDurations.Length, (float[]) null, (float[]) null, (float[]) null, 0);
      }
    }

    public override void OnAgentRemoved(
      Agent affectedAgent,
      Agent affectorAgent,
      AgentState agentState,
      KillingBlow blow)
    {
      base.OnAgentRemoved(affectedAgent, affectorAgent, agentState, blow);
      if (!affectedAgent.IsMainAgent)
        return;
      this.ResetTriggerFeedback();
      this.ResetTriggerVibration();
    }

    protected override void OnEndMission()
    {
      base.OnEndMission();
      this.SetTriggerState(MissionGamepadEffectsView.TriggerState.Off);
    }

    private void OnNativeOptionChanged(
      NativeOptions.NativeOptionsType changedNativeOptionsType)
    {
      if (changedNativeOptionsType != NativeOptions.NativeOptionsType.EnableVibration)
        return;
      int num = this._isAdaptiveTriggerEnabled ? 1 : 0;
      this._isAdaptiveTriggerEnabled = (double) NativeOptions.GetConfig(NativeOptions.NativeOptionsType.EnableVibration) != 0.0;
      this._usingAlternativeAiming = (double) NativeOptions.GetConfig(NativeOptions.NativeOptionsType.EnableAlternateAiming) != 0.0;
      if (num == 0 || this._isAdaptiveTriggerEnabled)
        return;
      this.ResetTriggerFeedback();
      this.ResetTriggerVibration();
    }

    private bool IsMissionModeApplicableForAdaptiveTrigger(MissionMode mode)
    {
      switch (mode)
      {
        case MissionMode.StartUp:
        case MissionMode.Battle:
        case MissionMode.Duel:
        case MissionMode.Stealth:
        case MissionMode.Tournament:
          return true;
        default:
          return false;
      }
    }

    private void HandleBowAdaptiveTriggers()
    {
      Agent mainAgent = this.Mission.MainAgent;
      switch (mainAgent != null ? mainAgent.GetCurrentActionStage(1) : Agent.ActionStage.None)
      {
        case Agent.ActionStage.None:
        case Agent.ActionStage.ReloadMidPhase:
        case Agent.ActionStage.ReloadLastPhase:
          this.SetTriggerState(this._usingAlternativeAiming ? MissionGamepadEffectsView.TriggerState.SoftTriggerFeedbackLeft : MissionGamepadEffectsView.TriggerState.SoftTriggerFeedbackRight);
          break;
        case Agent.ActionStage.AttackReady:
          float num1 = mainAgent.GetAimingTimer() - mainAgent.AgentDrivenProperties.WeaponUnsteadyBeginTime;
          if ((double) num1 > 0.0)
          {
            float num2 = mainAgent.AgentDrivenProperties.WeaponUnsteadyEndTime - mainAgent.AgentDrivenProperties.WeaponUnsteadyBeginTime;
            float num3 = MBMath.Lerp(0.0f, 1f, MBMath.ClampFloat(num1 / num2, 0.0f, 1f));
            float[] numArray1 = new float[1]{ num3 };
            float[] numArray2 = new float[1]
            {
              MBMath.ClampFloat(1f - num3, 0.1f, 1f)
            };
            float[] numArray3 = new float[1]{ 0.05f };
            if (this._usingAlternativeAiming)
              this.SetTriggerVibration(numArray1, numArray2, numArray3, numArray3.Length, (float[]) null, (float[]) null, (float[]) null, 0);
            else
              this.SetTriggerVibration((float[]) null, (float[]) null, (float[]) null, 0, numArray1, numArray2, numArray3, numArray3.Length);
            this._triggerState = MissionGamepadEffectsView.TriggerState.Vibration;
          }
          else
          {
            this.SetTriggerState(this._usingAlternativeAiming ? MissionGamepadEffectsView.TriggerState.SoftTriggerFeedbackLeft : MissionGamepadEffectsView.TriggerState.SoftTriggerFeedbackRight);
            float[] numArray4 = new float[1]{ 0.07f };
            float[] numArray5 = new float[1]{ 0.5f };
            float[] numArray6 = new float[1]{ 0.5f };
            if (this._usingAlternativeAiming)
              this.SetTriggerVibration(numArray4, numArray5, numArray6, numArray6.Length, (float[]) null, (float[]) null, (float[]) null, 0);
            else
              this.SetTriggerVibration((float[]) null, (float[]) null, (float[]) null, 0, numArray4, numArray5, numArray6, numArray6.Length);
          }
          if (this._usingAlternativeAiming)
          {
            this.SetTriggerWeaponEffect((byte) 0, (byte) 0, (byte) 0, (byte) 3, (byte) 7, (byte) 8);
            break;
          }
          this.SetTriggerWeaponEffect((byte) 0, (byte) 0, (byte) 0, (byte) 0, (byte) 0, (byte) 0);
          break;
        case Agent.ActionStage.AttackRelease:
          this.SetTriggerState(MissionGamepadEffectsView.TriggerState.Off);
          break;
        default:
          this.SetTriggerState(MissionGamepadEffectsView.TriggerState.Off);
          break;
      }
    }

    private void HandleCrossbowAdaptiveTriggers()
    {
      Agent mainAgent = this.Mission.MainAgent;
      switch (mainAgent != null ? mainAgent.GetCurrentActionStage(1) : Agent.ActionStage.None)
      {
        case Agent.ActionStage.AttackReady:
          if (!this._usingAlternativeAiming)
            break;
          this.SetTriggerWeaponEffect((byte) 0, (byte) 0, (byte) 0, (byte) 3, (byte) 7, (byte) 8);
          break;
        case Agent.ActionStage.AttackRelease:
          float[] rightTriggerAmplitudes = new float[1]
          {
            0.01f
          };
          float[] rightTriggerFrequencies = new float[1]
          {
            0.08f
          };
          float[] rightTriggerDurations = new float[1]
          {
            0.05f
          };
          this.SetTriggerVibration((float[]) null, (float[]) null, (float[]) null, 0, rightTriggerAmplitudes, rightTriggerFrequencies, rightTriggerDurations, rightTriggerDurations.Length);
          this.SetTriggerState(MissionGamepadEffectsView.TriggerState.Off);
          break;
        case Agent.ActionStage.ReloadMidPhase:
          this.SetTriggerState(MissionGamepadEffectsView.TriggerState.Off);
          break;
        default:
          if (this._usingAlternativeAiming)
            break;
          this.SetTriggerWeaponEffect((byte) 0, (byte) 0, (byte) 0, (byte) 3, (byte) 7, (byte) 8);
          break;
      }
    }

    private void HandleThrowableAdaptiveTriggers()
    {
      WeaponComponentData currentUsageItem = this.Mission.MainAgent.WieldedOffhandWeapon.CurrentUsageItem;
      int num = currentUsageItem != null ? (currentUsageItem.WeaponFlags.HasAnyFlag<WeaponFlags>(WeaponFlags.CanBlockRanged) ? 1 : 0) : 0;
      this._triggerFeedback[2] = (byte) 0;
      this._triggerFeedback[3] = (byte) 3;
      if (num != 0)
      {
        this._triggerFeedback[0] = (byte) 4;
        this._triggerFeedback[1] = (byte) 2;
      }
      else
      {
        this._triggerFeedback[0] = (byte) 0;
        this._triggerFeedback[1] = (byte) 0;
      }
      this.SetTriggerFeedback(this._triggerFeedback[0], this._triggerFeedback[1], this._triggerFeedback[2], this._triggerFeedback[3]);
    }

    private void HandleMeleeAdaptiveTriggers()
    {
      Agent mainAgent = this.Mission.MainAgent;
      MissionWeapon wieldedWeapon = mainAgent.WieldedWeapon;
      WeaponComponentData currentUsageItem1 = wieldedWeapon.CurrentUsageItem;
      bool flag = currentUsageItem1 != null && currentUsageItem1.WeaponFlags.HasAllFlags<WeaponFlags>(WeaponFlags.NotUsableWithOneHand);
      WeaponComponentData currentUsageItem2 = mainAgent.WieldedOffhandWeapon.CurrentUsageItem;
      int num1 = currentUsageItem2 != null ? (currentUsageItem2.WeaponFlags.HasAnyFlag<WeaponFlags>(WeaponFlags.CanBlockRanged) ? 1 : 0) : 0;
      if (flag)
      {
        this._triggerFeedback[2] = (byte) 3;
        this._triggerFeedback[3] = (byte) 0;
      }
      else if (wieldedWeapon.CurrentUsageItem == null)
      {
        this._triggerFeedback[2] = (byte) 0;
        this._triggerFeedback[3] = (byte) 0;
      }
      else
      {
        this._triggerFeedback[2] = (byte) 4;
        this._triggerFeedback[3] = (byte) 1;
      }
      int num2 = flag ? 1 : 0;
      if ((num1 | num2) != 0 || wieldedWeapon.CurrentUsageItem != null)
      {
        this._triggerFeedback[0] = (byte) 4;
        this._triggerFeedback[1] = (byte) 2;
      }
      else
      {
        this._triggerFeedback[0] = (byte) 0;
        this._triggerFeedback[1] = (byte) 0;
      }
      this.SetTriggerFeedback(this._triggerFeedback[0], this._triggerFeedback[1], this._triggerFeedback[2], this._triggerFeedback[3]);
    }

    private void HandleRangedSiegeEngineAdaptiveTriggers(RangedSiegeWeapon rangedSiegeWeapon)
    {
      switch (rangedSiegeWeapon)
      {
        case Ballista _:
        case FireBallista _:
          if (rangedSiegeWeapon.State == RangedSiegeWeapon.WeaponState.Idle)
          {
            this.SetTriggerWeaponEffect((byte) 0, (byte) 0, (byte) 0, (byte) 4, (byte) 6, (byte) 10);
            break;
          }
          if (rangedSiegeWeapon.State == RangedSiegeWeapon.WeaponState.Shooting || rangedSiegeWeapon.State == RangedSiegeWeapon.WeaponState.WaitingBeforeProjectileLeaving)
          {
            this.SetTriggerWeaponEffect((byte) 0, (byte) 0, (byte) 0, (byte) 0, (byte) 0, (byte) 0);
            float[] rightTriggerAmplitudes = new float[3]
            {
              0.2f,
              0.4f,
              0.2f
            };
            float[] rightTriggerFrequencies = new float[3]
            {
              0.2f,
              0.4f,
              0.2f
            };
            float[] rightTriggerDurations = new float[3]
            {
              0.2f,
              0.3f,
              0.2f
            };
            this.SetTriggerVibration((float[]) null, (float[]) null, (float[]) null, 0, rightTriggerAmplitudes, rightTriggerFrequencies, rightTriggerDurations, rightTriggerDurations.Length);
            break;
          }
          this.ResetTriggerFeedback();
          this.ResetTriggerVibration();
          break;
        default:
          this.ResetTriggerFeedback();
          this.ResetTriggerVibration();
          break;
      }
    }

    private UsableMachine GetUsableMachineFromUsableMissionObject(
      UsableMissionObject usableMissionObject)
    {
      if (usableMissionObject is StandingPoint standingPoint)
      {
        GameEntity gameEntity = standingPoint.GameEntity;
        while ((NativeObject) gameEntity != (NativeObject) null && !gameEntity.HasScriptOfType<UsableMachine>())
          gameEntity = gameEntity.Parent;
        if ((NativeObject) gameEntity != (NativeObject) null)
        {
          UsableMachine firstScriptOfType = gameEntity.GetFirstScriptOfType<UsableMachine>();
          if (firstScriptOfType != null)
            return firstScriptOfType;
        }
      }
      return (UsableMachine) null;
    }

    private void SetTriggerState(
      MissionGamepadEffectsView.TriggerState triggerState)
    {
      if (this._triggerState == triggerState)
        return;
      switch (triggerState)
      {
        case MissionGamepadEffectsView.TriggerState.Off:
          this.ResetTriggerFeedback();
          this.ResetTriggerVibration();
          break;
        case MissionGamepadEffectsView.TriggerState.SoftTriggerFeedbackLeft:
          this.SetTriggerFeedback((byte) 0, (byte) 2, (byte) 0, (byte) 0);
          this.SetTriggerWeaponEffect((byte) 0, (byte) 0, (byte) 0, (byte) 0, (byte) 0, (byte) 0);
          break;
        case MissionGamepadEffectsView.TriggerState.SoftTriggerFeedbackRight:
          this.SetTriggerFeedback((byte) 0, (byte) 0, (byte) 0, (byte) 2);
          this.SetTriggerWeaponEffect((byte) 0, (byte) 0, (byte) 0, (byte) 0, (byte) 0, (byte) 0);
          break;
        case MissionGamepadEffectsView.TriggerState.HardTriggerFeedbackLeft:
          this.SetTriggerFeedback((byte) 0, (byte) 4, (byte) 0, (byte) 0);
          this.SetTriggerWeaponEffect((byte) 0, (byte) 0, (byte) 0, (byte) 0, (byte) 0, (byte) 0);
          break;
        case MissionGamepadEffectsView.TriggerState.HardTriggerFeedbackRight:
          this.SetTriggerFeedback((byte) 0, (byte) 0, (byte) 0, (byte) 4);
          this.SetTriggerWeaponEffect((byte) 0, (byte) 0, (byte) 0, (byte) 0, (byte) 0, (byte) 0);
          break;
        case MissionGamepadEffectsView.TriggerState.WeaponEffect:
          this.SetTriggerWeaponEffect((byte) 0, (byte) 0, (byte) 0, (byte) 4, (byte) 7, (byte) 7);
          break;
        default:
          Debug.FailedAssert("Unexpected trigger state:" + (object) triggerState, "C:\\Develop\\MB3\\Source\\Bannerlord\\TaleWorlds.MountAndBlade.View\\MissionViews\\MissionGamepadEffectsView.cs", nameof (SetTriggerState), 500);
          break;
      }
      this._triggerState = triggerState;
    }

    private void ResetTriggerFeedback()
    {
      this._triggerFeedback[0] = (byte) 0;
      this._triggerFeedback[1] = (byte) 0;
      this._triggerFeedback[2] = (byte) 0;
      this._triggerFeedback[3] = (byte) 0;
      this.SetTriggerFeedback((byte) 0, (byte) 0, (byte) 0, (byte) 0);
      this.SetTriggerWeaponEffect((byte) 0, (byte) 0, (byte) 0, (byte) 0, (byte) 0, (byte) 0);
      this._triggerState = MissionGamepadEffectsView.TriggerState.Off;
    }

    private void SetTriggerFeedback(
      byte leftTriggerPosition,
      byte leftTriggerStrength,
      byte rightTriggerPosition,
      byte rightTriggerStrength)
    {
      TaleWorlds.InputSystem.Input.SetTriggerFeedback(leftTriggerPosition, leftTriggerStrength, rightTriggerPosition, rightTriggerStrength);
    }

    private void SetTriggerWeaponEffect(
      byte leftStartPosition,
      byte leftEnd_position,
      byte leftStrength,
      byte rightStartPosition,
      byte rightEndPosition,
      byte rightStrength)
    {
      TaleWorlds.InputSystem.Input.SetTriggerWeaponEffect(leftStartPosition, leftEnd_position, leftStrength, rightStartPosition, rightEndPosition, rightStrength);
    }

    private void ResetTriggerVibration()
    {
      float[] numArray = new float[1];
      this.SetTriggerVibration(numArray, numArray, numArray, 0, numArray, numArray, numArray, 0);
    }

    private void SetTriggerVibration(
      float[] leftTriggerAmplitudes,
      float[] leftTriggerFrequencies,
      float[] leftTriggerDurations,
      int numLeftTriggerElements,
      float[] rightTriggerAmplitudes,
      float[] rightTriggerFrequencies,
      float[] rightTriggerDurations,
      int numRightTriggerElements)
    {
      TaleWorlds.InputSystem.Input.SetTriggerVibration(leftTriggerAmplitudes, leftTriggerFrequencies, leftTriggerDurations, numLeftTriggerElements, rightTriggerAmplitudes, rightTriggerFrequencies, rightTriggerDurations, numRightTriggerElements);
    }

    private static void SetLightbarColor(float red, float green, float blue)
    {
      TaleWorlds.InputSystem.Input.SetLightbarColor(red, green, blue);
    }

    private enum TriggerState
    {
      Off,
      SoftTriggerFeedbackLeft,
      SoftTriggerFeedbackRight,
      HardTriggerFeedbackLeft,
      HardTriggerFeedbackRight,
      WeaponEffect,
      Vibration,
    }
  }
}
